package me.firstapp.search.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import me.firstapp.common.json.ListObject;
import me.firstapp.common.module.shop.JsonProduct;
import me.firstapp.common.utils.StrUtils;
import me.firstapp.search.service.ProductSearchService;
import me.firstapp.spi.shop.ProductService;

@Service
public class ProductSearchServiceImpl implements ProductSearchService {

	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	@Autowired
	private ProductService productService;

	@Override
	public void addData() {
		try {
			@SuppressWarnings("unchecked")
			List<JsonProduct> productList = (List<JsonProduct>) redisTemplate.opsForValue().get("productList");
			if (productList == null || productList.isEmpty()) {
				ListObject<JsonProduct> productResult = productService.findProducts(1);
				productList = productResult.getItems();
				redisTemplate.opsForValue().set("productList", productList);
			}
			if (productList != null && !productList.isEmpty()) {
				// 首先，我们需要定义一个词法分析器。
				// Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
				SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(Version.LUCENE_40);
				// 第二步，确定索引文件存储的位置
				Directory directory = FSDirectory.open(new File("/tmp/product_index"));
				// 第三步，创建IndexWriter，进行索引文件的写入。
				IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);
				IndexWriter iwriter = new IndexWriter(directory, config);
				// 第四步，内容提取，进行索引的存储。
				for (JsonProduct product : productList) {
					Document doc = new Document();
					String fieldName = "id";
					IndexableField field = new LongField(fieldName, product.getId(), Field.Store.YES);
					doc.add(field);

					fieldName = "name";
					field = new TextField(fieldName, product.getName(), Field.Store.YES);
					doc.add(field);

					iwriter.addDocument(doc);
				}
				iwriter.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public List<JsonProduct> search(String keyword) {
		List<JsonProduct> result = new ArrayList<>();
		Set<Long> productIds = new HashSet<>();
		try {
			Directory directory = FSDirectory.open(new File("/tmp/product_index"));
			// 第一步，打开存储位置
			DirectoryReader ireader = DirectoryReader.open(directory);
			// 第二步，创建搜索器
			IndexSearcher isearcher = new IndexSearcher(ireader);
			// 第三步，类似SQL，进行关键字查询
			// Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
			SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(Version.LUCENE_40);

			if (StrUtils.isNotNULL(keyword)) {
				QueryParser parser = new QueryParser(Version.LUCENE_40, "name", analyzer);
				Query query = parser.parse(keyword);
				ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs;
				for (int i = 0; i < hits.length; i++) {
					Document hitDoc = isearcher.doc(hits[i].doc);
					String idStr = hitDoc.get("id");
					if (StrUtils.isNotNULL(idStr)) {
						Long id = Long.valueOf(idStr);
						productIds.add(id);
					}
				}
			}
			@SuppressWarnings("unchecked")
			Map<Long, JsonProduct> productMap = (Map<Long, JsonProduct>) redisTemplate.opsForValue().get("productMap");
			if (productMap != null) {
				for (Long productId : productIds) {
					JsonProduct product = productMap.get(productId);
					result.add(product);
				}
			}
			if (productMap == null) {
				@SuppressWarnings("unchecked")
				List<JsonProduct> productList = (List<JsonProduct>) redisTemplate.opsForValue().get("productList");
				for (JsonProduct product : productList) {
					for (Long productId : productIds) {
						if (product.getId().equals(productId)) {
							result.add(product);
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

}
